import type { VNodeProps, AllowedComponentProps, Component } from "vue";

import type { FormItemProps, InputInstance, DatePickerInstance, RadioGroupInstance, TreeInstance } from "element-plus";

import { ElSelect, ElTreeSelect } from "element-plus";

import MerakXFormItem from "./index.vue";

type ExtractProps<T> = {
  -readonly [K in keyof Omit<Partial<T>, keyof VNodeProps | keyof AllowedComponentProps>]: T[K];
};

interface MerakXFormItemType extends Omit<Partial<FormItemProps>, "prop"> {
  prop: string;
  visible?: boolean;
  readonly?: boolean;
  render?: string | Component;
}

export type MerakXFormItemInstance = InstanceType<typeof MerakXFormItem>;

export type MerakXFormItemInput = {
  type?: "input";
  props?: ExtractProps<InputInstance["$props"]> & { numberType?: { integer?: number; decimal?: number } };
};

export type MerakXFormItemSelect = {
  type?: "select";
  props?: ExtractProps<InstanceType<typeof ElSelect>["$props"]>;
};

export type MerakXFormItemDatePicker = {
  type?: "datePicker";
  props?: ExtractProps<DatePickerInstance["$props"]>;
};

export type MerakXFormItemRadio = {
  type?: "radio";
  props?: ExtractProps<RadioGroupInstance["$props"]>;
};

export type MerakXFormItemTreeSelect = {
  type?: "treeSelect";
  props?: ExtractProps<InstanceType<typeof ElSelect>["$props"]> & ExtractProps<TreeInstance["$props"]>;
};

export type MerakXFormItemOption = {
  label: string | number;
  value: string | number | boolean;
  children?: MerakXFormItemOption[];
};

export interface MerakXFormItemOptions {
  field?: string;
  options?: MerakXFormItemOption[];
  queryOptions?: (field?: string) => Promise<MerakXFormItemOption[] | undefined>;
}

export interface MerakXFormItemChangeParams {
  prop: string;
  type: MerakXFormItemProps["type"];
  data: any;
}

export type MerakXFormItemProps = MerakXFormItemType &
  MerakXFormItemOptions &
  (MerakXFormItemInput | MerakXFormItemSelect | MerakXFormItemDatePicker | MerakXFormItemRadio | MerakXFormItemTreeSelect);

export default MerakXFormItem;
